from stock.base.base_spider_worker import BaseSpiderWorker, StockPlatForm
from utils.log_util import saveLog, prints
from utils.e_mail import sendMail
import threading
import datetime
import time


class StockWorker(BaseSpiderWorker):

    # 该时间点进行数据分析
    analyTimeHour = 14
    lastHour = -1

    # 板块下所有股票
    codeForPlate = None
    minuteCount = 0
    sleepTime = 10 * 60

    # 上次检测到的股票
    lastNoticeCode = []

    def __init__(self):
        super().__init__()

    def startThread(self):
        thread = threading.Thread(target=self.execution)
        thread.start()

    def execution(self):
        """
        任务线程
        """

        prints("股票检测服务已启动...")

        self.initThread()

        while True:
            nowTime = datetime.datetime.now()
            weekday = nowTime.weekday()
            hourNow = nowTime.hour
            minuteNow = nowTime.minute

            if weekday < 5:
                # 获取热门板块
                self.getStockCode(hourNow)

                if self.lastHour != hourNow:
                    # 隔天清空上次检测到的股票代码、更新最新价格
                    if self.lastHour == -1 or hourNow == 0:
                        saveLog("开始更新股票数据")
                        self.lastNoticeCode.clear()
                        self.updateStockCode()
                        self.updateStockPrice()
                        saveLog("更新股票数据完成")

                    # 指定时间进行人气股检测
                    if self.lastHour == -1 or hourNow == self.analyTimeHour:
                        self.noticeHotStock()

                # 股票交易时间内进行信号检测和板块下股票获取
                if self.lastHour == -1 or (hourNow > 9 and hourNow < 12) or (
                        hourNow > 12 and hourNow < 16):
                    self.monitorStock()
                self.lastHour = hourNow
            time.sleep(self.sleepTime)

    def monitorStock(self):
        """
        股票实时监测
        """
        try:
            codeResult = self.signalDetection(self.codeForPlate)

            if len(self.lastNoticeCode) != 0:
                codeResult = [
                    item for item in codeResult
                    if item not in self.lastNoticeCode
                ]

            if codeResult != None and len(codeResult) != 0:
                self.lastNoticeCode.extend(codeResult)

                stockResult = "、".join(codeResult)
                sendMail("检测到符合条件的股票",
                         "检测到符合条件的股票：" + stockResult,
                         timer=False)
                saveLog("检测到符合条件的股票：" + stockResult)
        except Exception as e:
            saveLog("股票信息解析异常:" + str(e))

    def getStockCode(self, hourNow):
        """
        获取热门板块下代码
        交易时间内，每30分钟获取热度最高的前一百个板块
        """
        if self.lastHour == -1 or (hourNow > 9
                                   and hourNow < 12) or (hourNow > 12
                                                         and hourNow < 16):
            if self.minuteCount <= 0:
                # 获取10日内主力净额大于零的板块
                saveLog("\n\n开始获取热门板块...")
                industryPlate, conceptPlate = self.getHotStockPlate()
                saveLog("热门板块获取完成")

                sortedArray = sorted(industryPlate + conceptPlate,
                                     key=lambda x: x[1],
                                     reverse=True)[0:50]

                # 获取热门板块下所有股票
                saveLog("获取热门板块下所有股票代码...")
                self.codeForPlate = self.getPlateStock(sortedArray)
                saveLog("获取热门板块下股票代码获取完成\n\n")
            elif self.minuteCount >= self.sleepTime * 3:
                self.minuteCount = 0
                return

            self.minuteCount = self.minuteCount + self.sleepTime
        else:
            self.minuteCount = 0

    def noticeHotStock(self):
        """
        人气热股通知
        """
        self.sqlite.delete_record("DELETE FROM article_stock WHERE time < " +
                                  str(self.getAgoTime()))

        # 主力资金流入多的股票
        stockList = self.mainPowerStock()
        resultCode = [
            item["股票名称"] for item in stockList if item["今日排名"] < 100
            and item["5日排名"] < 100 and item["10日排名"] < 100
        ]

        hotCodes, inMenoyCode = self.analyseStock()
        hotCodesStr = "、".join(hotCodes)
        inMenoyCodeStr = "、".join(inMenoyCode)
        powerCodeStr = "、".join(resultCode)

        noticeStr = ""
        if hotCodesStr != "":
            noticeStr = "日内人气股已公布：" + hotCodesStr + "\n\n"

        if inMenoyCodeStr != "":
            noticeStr = noticeStr + "十日内资金流入量大的股票已公布：" + inMenoyCodeStr + "\n\n"

        if powerCodeStr != "":
            noticeStr = noticeStr + "十日内受主力资金青睐股票已公布：" + powerCodeStr

        if noticeStr != "":
            sendMail("日内人气股已公布",
                     "日内人气股已公布：\n" + noticeStr,
                     timer=False,
                     send=True)
                     
            saveLog("日内人气股已公布：" + hotCodesStr)
            saveLog("十日内资金流入量大的股票已公布：" + inMenoyCodeStr)
            saveLog("主力资金流入大的股票已公布：" + powerCodeStr)

    def analyseStock(self):
        """
        板块分析
        """

        # 资金流入多的股票
        dayMoney, day3Money, day5Money, day10Money = self.dayMoreMoneyStock()
        inMoreMoneyStock = list(
            set([
                item[0]
                for item in (dayMoney + day3Money + day5Money + day10Money)
            ]))

        # 淘股吧热门股票
        hotCode = [item.split(" ")[0] for item in self.getHotStock()]

        # 讨论热度高的股票
        popularCode = [
            item[0] for item in self.getWebInfo(StockPlatForm.TG)
            if item[1] > 2
        ]

        # 价格过滤
        filterCode, filterPrice = self.getStandardSocket(inMoreMoneyStock +
                                                         hotCode + popularCode)

        inMoneyStockList = [
            item.股票名称 for item in filterPrice if item.股票名称 in inMoreMoneyStock
        ]
        hotStockList = [
            item.股票名称 for item in filterPrice if item.股票名称 in hotCode
        ]
        popularStockList = [
            item.股票名称 for item in filterPrice if item.股票名称 in popularCode
        ]

        # 按原来排序重新排序
        sortedInMoneyStock = [
            item for item in inMoreMoneyStock if item in inMoneyStockList
        ]
        sortedHotStock = [item for item in hotStockList if item in hotCode]
        sortedPopularStock = [
            item for item in popularStockList if item in popularCode
        ]

        maxList = sortedHotStock if len(sortedHotStock) > len(
            sortedPopularStock) else sortedPopularStock
        minList = sortedHotStock if len(sortedHotStock) <= len(
            sortedPopularStock) else sortedPopularStock

        # 热度高的股票，只获取前20个
        popCodeList = []
        for maxIndex in range(0, len(maxList) if len(maxList) < 20 else 20):
            codeStr = maxList[maxIndex]
            if codeStr not in popCodeList:
                popCodeList.append(codeStr)

            if len(minList) > maxIndex:
                minCodeStr = minList[maxIndex]
                if minCodeStr not in popCodeList:
                    popCodeList.append(minCodeStr)
        return popCodeList, sortedInMoneyStock

    def filterStock(self, stockList, plateList):
        """
        股票板块过滤
        """

        allStock = self.getAllStockBaseInfo()
        filterName = [item for item in allStock if item["f14"] in stockList]
        filterPrice = [
            item for item in filterName
            if item["f15"] != "-" and item["f15"] < self.limitMaxPrice
        ]
        filterPlate = self.getLivePlate([item["f14"] for item in filterPrice])

        filterMap = {}
        for key, value in filterPlate.items():
            for plate in plateList:
                if plate in value:
                    filterMap[key] = value
                    break
        return filterMap

    def dayMoreMoneyStock(self):
        """
        获取资金流入多的股票
        """
        day, day3, day5, day10 = self.intoMoneyStock()
        dayFilter = [
            item for item in day if isinstance(item[2], str) is False
            and item[2] < self.limitMaxPrice
        ]
        day3Filter = [
            item for item in day3 if isinstance(item[2], str) is False
            and item[2] < self.limitMaxPrice
        ]
        day5Filter = [
            item for item in day5 if isinstance(item[2], str) is False
            and item[2] < self.limitMaxPrice
        ]
        day10Filter = [
            item for item in day10 if isinstance(item[2], str) is False
            and item[2] < self.limitMaxPrice
        ]
        return dayFilter, day3Filter, day5Filter, day10Filter
